package mipo.top.base.service.impl;

import com.alibaba.fastjson.JSONObject;
import mipo.top.base.Dto.WechatDto;
import mipo.top.base.constant.wechatRegisterConstant;
import mipo.top.base.util.HttpUtil;
import mipo.top.users.domain.Logininfo;
import mipo.top.users.domain.Wxuser;
import mipo.top.users.mapper.LogininfoMapper;
import mipo.top.base.Dto.EmailDto;
import mipo.top.base.Dto.RegisterDto;
import mipo.top.base.constant.RegisterConstant;
import mipo.top.base.exception.BusinessException;
import mipo.top.base.service.IRegisterService;
import mipo.top.base.util.MD5Utils;
import mipo.top.base.util.StrUtils;
import mipo.top.users.domain.User;
import mipo.top.users.mapper.UserMapper;
import mipo.top.users.mapper.WxuserMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class RegisterServiceimpl implements IRegisterService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private WxuserMapper wxuserMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void registerPhone(RegisterDto dto) {
        this.confirmDto(dto);
        User user = Register2user(dto);
        Logininfo logininfo = user2logininfo(user);
        logininfoMapper.save(logininfo);
        user.setLogininfoId(logininfo.getId());
        userMapper.save(user);
    }

    @Override
    public void registerEmail(EmailDto dto) {
        this.Emailconfirm(dto);
        User user = Dto2User(dto);
        Logininfo logininfo = user2logininfo(user);
        logininfoMapper.save(logininfo);
        user.setLogininfoId(logininfo.getId());
        userMapper.save(user);
    }
    // 1.获取数据
    // 2.参数为空判断
    // 3.判断短信验证码是否正确
    // 4.根据电话查询t_user表
    // 5.外层创建Logininfo对象
    // 6.判断user用户是否存在，不存在帮助用户创建，存在则查询出logininfo信息
    // 查询不到用户说明此微信用户之前没有使用此手机号创建过账号，那么我们需要给此微信用户创建user对象&logininfo对象
    // 1.初始化user对象，并保存
    // 2.根据User对象创建logininfo对象
    // 3.保存logininfo信息
    // 4.将logininfo主键信息设置到user中
    // 5.更新user对象信息
    // 查询的到用户说明此微信用户之前使用此手机号创建过账号，那么我们查询出此用户的logininfo信息
    // 7.根据accessToken+openId获取微信个人信息
    // 因为响应的字段名称与t_wxuser表字段名称一致，所以可以直接使用JsonObject对象的parseObject方法，根据相同的字段名称赋值创建对象
    // 8.在Wxuser对象中保存user对象Id
    // 9.保存微信用户信息
    // 10.生成token保存到redis中，并返回前端
    // 生成UUID作为token存入到redis中设置有效期30分钟
    // 将用户敏感信息置空
    // 并设置token和用户信息到map中

    @Override
    public HashMap<String, Object> binderPhone(WechatDto dto) {
        if (dto.getPhone()==null){
            throw new BusinessException("绑定电话不能为空");
        }
        if (dto.getVerifyCode()==null){
            throw new BusinessException("绑定手机发送的验证码不能为空");
        }
        String VerifyCodeTemp = (String) redisTemplate.opsForValue().get(RegisterConstant.BINDERREGISTERKEY+ dto.getPhone());
        if(VerifyCodeTemp==null){
            throw new BusinessException("短信验证码已经失效");
        }
        String[] split = VerifyCodeTemp.split(":");
        String VerifyCode = split[0];
        if (!VerifyCode.equalsIgnoreCase(dto.getVerifyCode())){
            throw new BusinessException("两次短信验证码不一致");
        }
        User user = userMapper.findphone(dto.getPhone());
        Logininfo logininfo = new Logininfo();
        if (user==null){
            user = Binder2user(dto);
            logininfo = user2logininfo(user);
            logininfoMapper.save(logininfo);
            user.setLogininfoId(logininfo.getId());
            userMapper.save(user);
        }else {
            logininfo = logininfoMapper.findByUserId(user.getId());
        }
        String Wxurl = wechatRegisterConstant.USER_URL
                .replace("ACCESS_TOKEN", dto.getAccessToken())
                .replace("OPENID", dto.getOpenId());
        String httpGet = HttpUtil.httpGet(Wxurl);
        Wxuser wxuser = JSONObject.parseObject(httpGet, Wxuser.class);
        // 8.在Wxuser对象中保存user对象Id
        wxuser.setUserId(user.getId());
        // 9.保存微信用户信息
        wxuserMapper.save(wxuser);

        // 10.生成token保存到redis中，并返回前端
        // 生成UUID作为token存入到redis中设置有效期30分钟
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(
                token,
                logininfo,
                30,
                TimeUnit.MINUTES
        );
        // 将用户敏感信息置空
        logininfo.setPassword("");
        logininfo.setSalt("");
        // 并设置token和用户信息到map中
        HashMap<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("logininfo", logininfo);
        return map;

    }

    private User Binder2user(WechatDto dto) {
        User user = new User();
        user.setUsername(dto.getPhone());
        user.setPhone(dto.getPhone());
        String salt = StrUtils.getComplexRandomString(32);
        String password = "123";
        String md5passwoed = MD5Utils.encrypByMd5(salt + password);
        user.setPassword(md5passwoed);
        user.setSalt(salt);
        user.setState(1);
        user.setCreatetime(new Date());
        return user;
    }

    //邮箱注册
    private User Dto2User(EmailDto dto) {
        String s = StrUtils.getComplexRandomString(32);
        String password = dto.getPassword();
        String md5password = MD5Utils.encrypByMd5(s + password);
        return User.builder()
                .username(dto.getEmail())
                .email(dto.getEmail())
                .salt(s)
                .password(md5password)
                .state(1)
                .createtime(new Date())
                .build();
    }

    private void Emailconfirm(EmailDto dto){
        String emailCodeTemp = (String) redisTemplate.opsForValue().get(RegisterConstant.EMAILREGISTERKEY + dto.getEmail());
        if(emailCodeTemp==null){
            throw new BusinessException("邮箱验证码已经失效");
        }
        String[] split = emailCodeTemp.split(":");
        String smsCode = split[0];
        if (!smsCode.equalsIgnoreCase(dto.getEmailCodeValue())){
            throw new BusinessException("两次短信验证码不一致");
        }
        if (!dto.getConfirmPassword().equals(dto.getPassword())){
            throw new BusinessException("两次密码不一致");
        }
    }

    private Logininfo user2logininfo(User user) {
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user,logininfo);
        logininfo.setType(1);
        return logininfo;
    }

    private User Register2user(RegisterDto dto){
        String s = StrUtils.getComplexRandomString(32);
        String password = s + dto.getPassword();
        String md5Password = MD5Utils.encrypByMd5(password);
        return User.builder()
                .username(dto.getPhone())
                .phone(dto.getPhone())
                .salt(s)
                .password(md5Password)
                .state(1)
                .createtime(new Date())
                .build();
    }

    private void confirmDto(RegisterDto dto){
        String smsCodeTemp = (String) redisTemplate.opsForValue().get(RegisterConstant.PHONEREGISTERKEY + dto.getPhone());
        if(smsCodeTemp==null){
            throw new BusinessException("短信验证码已经失效");
        }
        String[] split = smsCodeTemp.split(":");
        String smsCode = split[0];
        if (!smsCode.equalsIgnoreCase(dto.getSmsCodeValue())){
            throw new BusinessException("两次短信验证码不一致");
        }
        if (!dto.getConfirmPassword().equals(dto.getPassword())){
            throw new BusinessException("两次密码不一致");
        }
    }
}
